package org.hfy;

import org.hfy.calc.AnalysisElement;
import org.hfy.collections.helper.Production;
import org.hfy.collections.helper.Symbol;
import org.hfy.collections.helper.SymbolString;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @Description: 测试样例
 * @Author: Takagi
 * @date: 2023/4/23
 */
public class Case {
    /*
     * @Author Takagi
     * @Description:
     * @date: 2023/4/27
     * @param
     * @return * @return List<Production>
     **/
    public static List<Production> getProductions() {
        List<Production> productions = new LinkedList<>();
        productions.add(new Production(
                new Symbol("L"),
                new SymbolString("E")
        ));
        productions.add(new Production(
                new Symbol("E"),
//                new SymbolString("E", "+", "T")
                new SymbolString("T", "R")
        ));
//        productions.add(new Production(
//                new Symbol("E"),
//                new SymbolString("T")
//        ));
        productions.add(new Production(
                new Symbol("R"),
                new SymbolString("+", "T", "R")
        ));
        productions.add(new Production(
                new Symbol("R"),
                new SymbolString(Constants.EPSILON)
        ));
//        productions.add(new Production(
//                new Symbol("T"),
//                new SymbolString("T", "*", "F")
//        ));
        productions.add(new Production(
                new Symbol("T"),
                new SymbolString("F", "M")
        ));
        productions.add(new Production(
                new Symbol("M"),
                new SymbolString("*", "F", "M")
        ));
//        productions.add(new Production(
//                new Symbol("T"),
//                new SymbolString("F")
//        ));
        productions.add(new Production(
                new Symbol("M"),
                new SymbolString(Constants.EPSILON)
        ));
        productions.add(new Production(
                new Symbol("F"),
                new SymbolString("(", "E", ")")
        ));
        productions.add(new Production(
                new Symbol("F"),
                new SymbolString("digit")
        ));
        return productions;
    }

    /*
     * @Author Takagi
     * @Description: 获取起始符号
     * @date: 2023/4/27
     * @param
     * @return * @return Symbol
     **/
    public static Symbol getStartSymbol() {
        return new Symbol("L");
    }

    /*
     * @Author Takagi
     * @Description: 获取输入符号串
     * @date: 2023/4/27
     * @param
     * @return * @return SymbolString
     **/
    public static SymbolString getPredictedString() {
        return new SymbolString(
                "digit", "+", "digit"
//                "digit", "*", "digit", "+"
//                "digit", "+", "digit", "+", "digit", "*", "digit"
//                "(", "digit", "+", "digit", ")", "*", "digit"
        );
    }

    /*
     * @Author Takagi
     * @Description: 自定义产生式翻译方案
     * @date: 2023/5/28
     * @param
     * @return * @return Map<List<SymbolString>>
     **/
    public static Map<Production, List<SymbolString>> getProductionTranslation() {
        Map<Production, List<SymbolString>> res = new HashMap<>();
        List<SymbolString> translate;
        Production production;
        // L -> E {print(E.val)}
        production = new Production(
                new Symbol("L"),
                new SymbolString("E")
        );
        translate = new LinkedList<>();
        translate.add(new SymbolString("E"));
        translate.add(new SymbolString("{", "print", "(", "E.val", ")", "}"));
        res.put(production, translate);

        // E -> T {R.i = T.val} R {E.val = R.s}
        production = new Production(
                new Symbol("E"),
                new SymbolString("T", "R")
        );
        translate = new LinkedList<>();
        translate.add(new SymbolString("T"));
        translate.add(new SymbolString("{", "R.i", "=", "T.val", "}"));
        translate.add(new SymbolString("R"));
        translate.add(new SymbolString("{", "E.val", "=", "R.s", "}"));
        res.put(production, translate);

        // R -> +T {R1.i = R.i + T.val} R {R.s = R1.i}
        production = new Production(
                new Symbol("R"),
                new SymbolString("+", "T", "R")
        );
        translate = new LinkedList<>();
        translate.add(new SymbolString("+"));
        translate.add(new SymbolString("T"));
        translate.add(new SymbolString("{", "R.i", "=", "R.i", "+", "T.val", "}"));
        translate.add(new SymbolString("R"));
        translate.add(new SymbolString("{", "R.s", "=", "R.s", "}"));
        res.put(production, translate);

        // R -> epsilon {R.s = R.i}
        production = new Production(
                new Symbol("R"),
                new SymbolString(Constants.EPSILON)
        );
        translate = new LinkedList<>();
        translate.add(new SymbolString(Constants.EPSILON));
        translate.add(new SymbolString("{", "R.s", "=", "R.i", "}"));
        res.put(production, translate);

        // T -> F {M.i = F.val} M {T.val = M.s}
        production = new Production(
                new Symbol("T"),
                new SymbolString("F", "M")
        );
        translate = new LinkedList<>();
        translate.add(new SymbolString("F"));
        translate.add(new SymbolString("{", "M.i", "=", "F.val", "}"));
        translate.add(new SymbolString("M"));
        translate.add(new SymbolString("{", "T.val", "=", "M.s", "}"));
        res.put(production, translate);

        // M -> *F {M1.i = M.i * F.val} M {M.s = M1.i}
        production = new Production(
                new Symbol("M"),
                new SymbolString("*", "F", "M")
        );
        translate = new LinkedList<>();
        translate.add(new SymbolString("*"));
        translate.add(new SymbolString("F"));
        translate.add(new SymbolString("{", "M.i", "=", "M.i", "*", "F.val", "}"));
        translate.add(new SymbolString("M"));
        translate.add(new SymbolString("{", "M.s", "=", "M.s", "}"));
        res.put(production, translate);

        // M -> epsilon {M.s = M.i}
        production = new Production(
                new Symbol("M"),
                new SymbolString(Constants.EPSILON)
        );
        translate = new LinkedList<>();
        translate.add(new SymbolString(Constants.EPSILON));
        translate.add(new SymbolString("{", "M.s", "=", "M.i", "}"));
        res.put(production, translate);

        // F -> (E) {F.val = E.val}
        production = new Production(
                new Symbol("F"),
                new SymbolString("(", "E", ")")
        );
        translate = new LinkedList<>();
        translate.add(new SymbolString("("));
        translate.add(new SymbolString("E"));
        translate.add(new SymbolString(")"));
        translate.add(new SymbolString("{", "F.val", "=", "E.val", "}"));
        res.put(production, translate);

        // F -> digit {F.val = digit.lexval}
        production = new Production(
                new Symbol("F"),
                new SymbolString("digit")
        );
        translate = new LinkedList<>();
        translate.add(new SymbolString("digit"));
        translate.add(new SymbolString("{", "F.val", "=", "digit.lexval", "}"));
        res.put(production, translate);
        return res;
    }
}
